home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-01-02 | 26.7 KB | 1,145 lines | [TEXT/????] |
- //
- // DOWNLOAD.CPP
- //
- // Copyright (C) Microsoft Corporation, 1996
- //
-
- #include "headers.h"
- #include "binhex.h"
- #include "urlapi.h"
- #include <Files.h>
- #include <Folders.h>
- #include <Resources.h>
- #include <CodeFragments.h>
- #include "urlmonsupport.h"
-
- FORMATETC g_FileFormatEtc = {
- CF_NULL,
- NULL,
- DVASPECT_CONTENT,
- -1,
- TYMED_FILE
- };
-
- char g_szExplorerFolderName[] = "\pExplorer";
- char g_szCacheFolderName[] = "\pActiveX Cache";
- OLECHAR g_szFileVersion[] = "FileVersion";
- OLECHAR g_szDestDir[] = "destdir";
- OLECHAR g_szVersion[] = "version";
-
- BOOL FindPrivateFolder(short *foundvRefNum, long *foundDirID, long ParentDirID, StringPtr FolderName);
- BOOL FindExplorerFolder(short *foundvRefNum, long *foundDirID);
- BOOL GetVersionFromString(LPOLESTR pszString, LPDWORD pdwVersion);
- BOOL CheckFileVersion(LPOLESTR pszFile, DWORD dwMinimumVersion, BOOL fUseExtensionsFolder);
- HRESULT RegisterOleFragment(FSSpec *spec, BOOL fRegister);
-
- typedef HRESULT ( *LPFNREGISTERSERVER)(void);
-
-
- CCodeDownload::CCodeDownload()
- {
- mRefCount = 1; // reference count of object
- mEnumKeyP = 0;
- mSiteP = NULL;
- mQueueP = NULL;
- mDownloadResult = 0;
- mStreamDataP = NULL;
- mProcessINF = false;
- mEnd = NULL;
- mCurrent = NULL;
- mLastSectionMatch = NULL;
- mStreamLength = 0;
- }
-
- CCodeDownload::~CCodeDownload()
- {
- }
-
- //
- // CCodeDownload::QueueDownload
- //
-
- void
- CCodeDownload::QueueDownload(CXSite *inSiteP)
- {
- QUEUED_DOWNLOAD *QueueEntryP;
-
- if (mSiteP == NULL) {
- // No downloads are in progress, likely because this is the first one
- // in, so just start it up.
- StartDownload(inSiteP);
- } else {
- if ((QueueEntryP = (QUEUED_DOWNLOAD *)
- CoTaskMemAlloc(sizeof(QUEUED_DOWNLOAD))) != NULL) {
- QueueEntryP->SiteP = inSiteP;
- QueueEntryP->NextP = mQueueP;
- mQueueP = QueueEntryP;
- }
- }
- }
-
- //
- // CCodeDownload::StartNextDownload
- //
-
- void
- CCodeDownload::StartNextDownload(void)
- {
- QUEUED_DOWNLOAD *QueueEntryP;
- CXSite *SiteP;
- HRESULT hr;
-
- while (mQueueP != NULL)
- {
- // Unlink the queued entry from the list.
- QueueEntryP = mQueueP;
- mQueueP = QueueEntryP->NextP;
- SiteP = QueueEntryP->SiteP;
- CoTaskMemFree(QueueEntryP);
-
- // Check if the object still requires a download. The download may no
- // longer be necessary if another site already downloaded all the code
- // that this site requires.
- hr = SiteP->CreateControl(false);
- if (hr == REGDB_E_CLASSNOTREG || hr == CO_E_DLLNOTFOUND)
- {
- if (StartDownload(SiteP))
- return;
- }
- SiteP->Release();
- }
-
- }
-
- //
- // CCodeDownload::StartDownload
- //
- // Fires off a new code download cycle.
- //
- // Note as a result of being called from StartNextDownload, we may not be
- // running in the "context" of the Netscape plugin that this pSite relates to.
- //
-
- BOOL
- CCodeDownload::StartDownload(CXSite *inSiteP)
- {
- BOOL fSuccess = false;
- FILEXTN FileType = GetFileTypeFromExtension(inSiteP->m_pszCodeURL);
-
- mProcessINF = FileType == FILEXTN_INF;
- mSiteP = inSiteP; // This is the current download site
- if(FileType != FILEXTN_UNKNOWN)
- fSuccess = OpenStream(inSiteP, mProcessINF, inSiteP->m_pszCodeURL);
- // The site no longer needs this memory, so free it up now.
- // CoTaskMemFree(inSiteP->m_pszCodeURL);
- DisposePtr(inSiteP->m_pszCodeURL);
- inSiteP->m_pszCodeURL = NULL;
- if(!fSuccess)
- {
- if(mSiteP)
- mSiteP->Release();
- mSiteP = NULL;
- }
- return fSuccess;
- }
-
- BOOL
- CCodeDownload::OpenStream(CXSite *inSiteP, Boolean IsINFFile, LPOLESTR URLString)
- {
- BOOL fSuccess = FALSE;
-
- {
- LPBINDHOST BindSiteP;
- LPENUMFORMATETC pEnum = NULL;
- LPMONIKER URLMoniker = NULL;
- HRESULT hr = E_FAIL;
- LPBINDCTX BindContext = NULL;
-
- inSiteP->QueryInterface(IID_IBindHost, (LPVOID *) &BindSiteP);
-
- if(BindSiteP)
- {
-
- BindSiteP->CreateMoniker((LPOLESTR)URLString, NULL, &URLMoniker, 0);
- if(URLMoniker)
- {
- LPVOID Dummy;
-
- // if inf file, don't register enumerator so we get a stream not a file
- if(!IsINFFile)
- {
- CreateFormatEnumerator(1, &g_FileFormatEtc, &pEnum);
- if(pEnum)
- {
- CreateBindCtx( 0, &BindContext);
- if(BindContext)
- RegisterFormatEnumerator(BindContext, pEnum, 0);
- }
- }
- if(IsINFFile || BindContext)
- {
- hr = BindSiteP->MonikerBindToStorage(URLMoniker, BindContext,
- (IBindStatusCallback*)this, IID_IStream, &Dummy);
- if(hr == E_PENDING)
- hr = S_OK;
- if(BindContext)
- BindContext->Release();
- URLMoniker->Release();
- }
- if(pEnum)
- pEnum->Release();
- }
- BindSiteP->Release();
- }
- if(hr == S_OK)
- {
- fSuccess = TRUE;
- }
- }
-
- return fSuccess;
- }
-
- //
- // CCodeDownload::ProcessNextSection
- //
-
- void
- CCodeDownload::ProcessNextSection(void)
- {
- BOOL fResult;
- OLECHAR szKeyName[MAX_PATH];
- OLECHAR szBuffer[64];
- OLECHAR szURL[MAX_URL_STRING];
- BOOL fUseExtensionsFolder;
- CLSID clsid;
- DWORD dwMinimumVersion;
-
- // Get the name of the next section from the .inf to download.
- ProcessNext:
- if (mEnumKeyP == NULL) {
- fResult = GetFirstKey("Add.Code", &mEnumKeyP, szKeyName,
- sizeof(szKeyName));
- } else {
- fResult = GetNextKey(&mEnumKeyP, szKeyName,
- sizeof(szKeyName));
- }
-
- if (!fResult)
- {
- // destroy the inf file data
- CoTaskMemFree(mStreamDataP);
- mStreamDataP = NULL;
- // There aren't any more sections to process, so attempt to create the
- // site's object.
- mSiteP->CreateControl(false);
- mSiteP->Release();
- mSiteP = NULL;
- mEnumKeyP = NULL;
- mLastSectionMatch = NULL;
- goto StartNextDownload;
- }
-
- GetProfileString("Add.Code", szKeyName, szKeyName,
- sizeof(szKeyName));
-
- // Get the minimum required version of the module.
- dwMinimumVersion = 0;
- if (GetProfileString(szKeyName, g_szFileVersion, szBuffer,
- sizeof(szBuffer))) {
- if (szBuffer[0] != '\0') {
- // If incorrectly formed, the following will return FALSE and
- // dwMinimumVersion will continue to be zero. Should we treat that
- // as a download failure?
- GetVersionFromString(szBuffer, &dwMinimumVersion);
- }
- }
-
- // Get the folder that this file is supposed to go in-- either the ActiveX
- // Cache or the Extensions folder.
- fUseExtensionsFolder = FALSE;
- if (GetProfileString(szKeyName, g_szDestDir, szBuffer,
- sizeof(szBuffer))) {
- // These magic numbers are LDID_WIN and LDID_SYS as defined by Windows
- // .INF files.
- if (strcmp(g_szDestDir, "10") || strcmp(g_szDestDir, "11"))
- fUseExtensionsFolder = TRUE;
- }
-
- // Get the URL that points at the code for this component.
- if (!GetProfileString(szKeyName, "file-mac-ppc", szURL,
- sizeof(szURL))) {
- if (!GetProfileString(szKeyName, "file", szURL,
- sizeof(szURL))) {
- szURL[0] = '\0';
- }
- }
-
- // If the file's URL is the magic "ignore", then this file is not required
- // for this platform, so we can skip to the next .inf line.
- if (strcmp(szURL, "ignore") == 0)
- goto ProcessNext;
-
- // Determine if a locally installed copy of the code exists and if it's an
- // adequate version to use.
- if (GetProfileString(szKeyName, "clsid", szBuffer,
- sizeof(szBuffer))) {
- // If the string is incorrectly formed, bail out.
- if (CLSIDFromString(szBuffer, &clsid) != S_OK)
- goto StartNextDownload;
- // If the handler for this CLSID is okay, then we're fine... go to the
- // next line.
- if (CheckCLSIDVersion(clsid, dwMinimumVersion))
- goto ProcessNext;
- } else {
- // If this file version is okay, then we're fine... go to the next line.
- if (CheckFileVersion(szKeyName, dwMinimumVersion, fUseExtensionsFolder))
- goto ProcessNext;
- }
-
- // The file extension must be BinHex... we do not support recursive .INF
- // files and we don't know how to handle any other file type.
- if (GetFileTypeFromExtension(szURL) != FILEXTN_HQX)
- goto StartNextDownload;
-
- if(OpenStream(mSiteP, false, szURL))
- {
- return;
- }
-
- StartNextDownload:
- StartNextDownload();
- return;
- }
-
- //
- // CCodeDownload::InfAvailable
- //
- // Called by the .inf stream notification object when its transfer is complete.
- //
-
- void
- CCodeDownload::InfAvailable(BOOL fSuccess)
- {
- if (fSuccess)
- {
- ProcessNextSection();
- }
- else
- {
- // If the transfer was not successful, bail on this download and start
- // the next one.
- if(mSiteP)
- mSiteP->Release();
- mSiteP = NULL;
- StartNextDownload();
- }
- }
-
- //
- // CCodeDownload::CodeAvailable
- //
- // Called by the code stream notification object when its transfer is complete.
- //
-
- void
- CCodeDownload::CodeAvailable(BOOL fSuccess)
- {
- if (fSuccess)
- {
- if (mProcessINF)
- {
- ProcessNextSection();
- }
- else
- {
- // This was a straight code download, not driven by an .INF, so we
- // can attempt to create the object now.
- mSiteP->CreateControl(false);
- mSiteP->Release();
- mSiteP = NULL;
- StartNextDownload();
- }
- }
- else
- {
- // If the transfer was not successful, bail on this download and start
- // the next one.
- if(mSiteP)
- mSiteP->Release();
- mSiteP = NULL;
- StartNextDownload();
- }
- }
-
- //
- // FindPrivateFolder
- //
- // Returns the volume and directory reference of the specified folder name from
- // the specified parent directory, making the directory if necessary.
- //
-
- BOOL FindPrivateFolder(short *foundvRefNum, long *foundDirID, long ParentDirID, StringPtr FolderName)
- {
- CInfoPBRec pb;
- HFileParam hb;
-
- pb.dirInfo.ioNamePtr = FolderName;
- pb.dirInfo.ioFDirIndex = 0;
- pb.dirInfo.ioVRefNum = *foundvRefNum;
- pb.dirInfo.ioDrDirID = ParentDirID;
- pb.dirInfo.ioACUser = 0;
-
- if (PBGetCatInfoSync(&pb) == noErr) {
- // The Win32 code currently bails its cache folder is not a folder.
- if (pb.dirInfo.ioFlAttrib & ioDirMask) {
- *foundDirID = pb.dirInfo.ioDrDirID;
- return TRUE;
- }
- } else {
- hb.ioNamePtr = (StringPtr) FolderName;
- hb.ioVRefNum = *foundvRefNum;
- hb.ioDirID = ParentDirID;
-
- if (PBDirCreateSync((union HParamBlockRec *) &hb) == noErr) {
- *foundDirID = hb.ioDirID;
- return TRUE;
- }
- }
-
- return FALSE;
- }
-
- //
- // FindExplorerFolder
- //
- // Returns the volume and directory reference of the Internet Explorer folder.
- //
-
- BOOL FindExplorerFolder(short *foundvRefNum, long *foundDirID)
- {
- BOOL fResult;
- long ParentDirID;
-
- if (FindFolder((short) kOnSystemDisk, kPreferencesFolderType, kCreateFolder,
- foundvRefNum, &ParentDirID) == noErr) {
- fResult = FindPrivateFolder(foundvRefNum, foundDirID, ParentDirID,
- (StringPtr) g_szExplorerFolderName);
- } else {
- fResult = FALSE;
- }
-
- return fResult;
- }
-
- //
- // FindActiveXCacheFolder
- //
- // Returns the volume and directory reference of the ActiveX cache folder.
- //
-
- BOOL
- FindActiveXCacheFolder(short *foundvRefNum, long *foundDirID)
- {
- BOOL fResult;
- long ParentDirID;
-
- if (FindExplorerFolder(foundvRefNum, &ParentDirID)) {
- fResult = FindPrivateFolder(foundvRefNum, foundDirID, ParentDirID,
- (StringPtr) g_szCacheFolderName);
- } else {
- fResult = FALSE;
- }
-
- return fResult;
- }
-
- //
- // FindDownloadFolder
- //
- // Returns the volume and directory reference of the ActiveX cache or the
- // Extensions folder
- //
-
- BOOL
- FindDownloadFolder(short *foundvRefNum, long *foundDirID, BOOL fExtensionsFolder)
- {
- BOOL fResult;
-
- if (fExtensionsFolder) {
- fResult = (FindFolder((short) kOnSystemDisk, kExtensionFolderType,
- kCreateFolder, foundvRefNum, foundDirID) == noErr);
- } else {
- fResult = FindActiveXCacheFolder(foundvRefNum, foundDirID);
- }
-
- return fResult;
- }
-
- //
- // GetFileTypeFromExtension
- //
-
- FILEXTN
- GetFileTypeFromExtension(LPOLESTR pszURL)
- {
- FILEXTN filextn;
- LPOLESTR pszCurrent;
- LPOLESTR pszExtension;
-
- for (pszCurrent = pszURL, pszExtension = NULL; *pszCurrent; pszCurrent++) {
- if (*pszCurrent == '.') {
- pszExtension = pszCurrent + 1;
- } else {
- if (*pszCurrent == '/' || *pszCurrent == '\\') {
- pszExtension = NULL;
- }
- }
- }
-
- filextn = FILEXTN_UNKNOWN;
- if (strcmp(pszExtension, "hqx") == 0) {
- filextn = FILEXTN_HQX;
- } else {
- if (strcmp(pszExtension, "inf") == 0) {
- filextn = FILEXTN_INF;
- }
- }
-
- return filextn;
- }
-
- //
- // GetVersionFromFile
- //
- // Returns the version from the specified file's "vers" resource.
- //
-
- BOOL
- GetVersionFromFile(FSSpec *spec, LPDWORD pdwVersion)
- {
- BOOL fResult = FALSE;
- short resFile;
- Handle hResource;
-
- if ((resFile = FSpOpenResFile(spec, fsRdPerm)) != -1) {
- if ((hResource = Get1Resource('vers', 1)) != nil) {
- if (GetHandleSize(hResource) > sizeof(DWORD)) {
- // Extract the version number from the resource, stripping off
- // the release stage byte.
- *pdwVersion = (*((LPDWORD)(*hResource))) & 0xFFFF00FF;
- fResult = TRUE;
- }
- }
- CloseResFile(resFile);
- }
-
- return fResult;
- }
-
- //
- // GetVersionFromString
- //
-
- BOOL
- GetVersionFromString(LPOLESTR pszString, LPDWORD pdwVersion)
- {
- BYTE parts[4] = { 0, 0, 0, 0 };
- UINT CurrentPart = 0;
- UINT n = 0;
-
- while (TRUE) {
- if (*pszString == ',' || *pszString == '\0') {
- if (CurrentPart >= 4)
- return FALSE;
- parts[CurrentPart++] = (BYTE) n;
- n = 0;
- if (*pszString == '\0')
- break;
- } else {
- if (*pszString < '0' || *pszString > '9')
- return FALSE;
- // The 'vers' resource stores numbers in BCD format.
- n = n * 16 + (*pszString - '0');
- }
- pszString++;
- }
-
- // Note that we ignore the "c" element from "version=a,b,c,d" because
- // GetVersionFromFile returns a number of the form "a,b,0,d"
- *pdwVersion = (((DWORD) parts[0]) << 24) + (((DWORD) parts[1]) << 16) +
- (((DWORD) parts[3]) << 0);
- return TRUE;
- }
-
- //
- // GetVersionFromURL
- //
- // Returns the "version" from the specified URL string. As a side effect, the
- // string will have any optional parameters "stripped off" by nulling out any
- // present '#' character.
- //
-
- BOOL
- GetVersionFromURL(LPOLESTR pszURL, LPDWORD pdwVersion)
- {
- LPOLESTR pszString;
- LPOLESTR pszVersionStart;
-
- if ((pszString = strchr(pszURL, '#')) == NULL)
- return FALSE;
- *pszString++ = '\0'; // Zap the '#' character
- pszVersionStart = pszString;
-
- if ((pszString = strchr(pszString, '=')) == NULL)
- return FALSE;
- *pszString++ = '\0'; // Zap the '=' character
-
- if (strcmp(pszVersionStart, g_szVersion) != 0)
- return FALSE;
-
- return GetVersionFromString(pszString, pdwVersion);
- }
-
- //
- // CheckFileVersion
- //
- // Returns TRUE if the specified file from the specified folder is at least the
- // specified minimum version, else returns FALSE.
- //
-
- BOOL
- CheckFileVersion(LPOLESTR pszFile, DWORD dwMinimumVersion, BOOL
- fUseExtensionsFolder)
- {
- BOOL fResult = FALSE;
- DWORD dwFileVersion;
- FSSpec spec;
-
- if (FindDownloadFolder(&spec.vRefNum, &spec.parID, fUseExtensionsFolder)) {
- c2pstr(pszFile);
- if (FSMakeFSSpec(spec.vRefNum, spec.parID, (StringPtr) pszFile,
- &spec) == noErr) {
- if (dwMinimumVersion != 0) {
- if (GetVersionFromFile(&spec, &dwFileVersion) &&
- (dwMinimumVersion <= dwFileVersion))
- fResult = TRUE;
- } else {
- // No minimum version specified; simply checks that the file
- // exists.
- fResult = TRUE;
- }
- }
- p2cstr((StringPtr) pszFile);
- }
-
- return fResult;
- }
-
-
- //
- // CCodeDownload::IUnknown::QueryInterface
- //
- // Returns a pointer to the specified interface on a component to which a
- // client currently holds an interface pointer.
- //
- STDMETHODIMP
- CCodeDownload::QueryInterface(REFIID RefID, void** Obj)
- {
- void* pv = nil;
-
- if (RefID == IID_IUnknown || RefID == IID_IBindStatusCallback)
- pv = (LPVOID)(IBindStatusCallback* ) this;
-
- *Obj = pv;
-
- // if we got an interface, ref it and return ok
- if ( pv )
- {
- ((IUnknown*) pv)->AddRef();
- return S_OK;
- }
- else
- return E_NOINTERFACE;
- }
-
-
- //
- // CCodeDownload::IUnknown::AddRef
- //
- // Increments the reference count for the calling interface.
- //
- STDMETHODIMP_(ULONG)
- CCodeDownload::AddRef(void)
- {
- return ++mRefCount;
- }
-
-
- //
- // CCodeDownload::IUnknown::Release
- //
- // Decrements the reference count for the calling interface on a object. If
- // the reference count on the object falls to zero, the object is freed.
- //
- STDMETHODIMP_(ULONG)
- CCodeDownload::Release(void)
- {
- if (--mRefCount != 0)
- return mRefCount;
-
- // delete this;
- return 0;
- }
-
- //=--------------------------------------------------------------------------=
- // CCodeDownload::IBindStatusCallback::OnStartBinding
- //=--------------------------------------------------------------------------=
- //
- STDMETHODIMP
- CCodeDownload::OnStartBinding(DWORD BSCOption, IBinding* aBinding)
- {
- #pragma unused (BSCOption, aBinding)
- // m_pib->AddRef();
- mDownloadResult = FALSE;
-
- return S_OK;
- }
-
-
- //=--------------------------------------------------------------------------=
- // CCodeDownload::IBindStatusCallback::GetPriority
- //=--------------------------------------------------------------------------=
- //
- STDMETHODIMP
- CCodeDownload::GetPriority(LONG *Priority)
- {
- *Priority = 0;
- return S_OK;
- }
-
-
- //=--------------------------------------------------------------------------=
- // CCodeDownload::IBindStatusCallback::OnLowResource
- //=--------------------------------------------------------------------------=
- //
- STDMETHODIMP
- CCodeDownload::OnLowResource(DWORD reserved)
- {
- #pragma unused (reserved)
- return S_OK;
- }
-
-
- //=--------------------------------------------------------------------------=
- // CCodeDownload::IBindStatusCallback::OnProgress
- //=--------------------------------------------------------------------------=
- //
- STDMETHODIMP
- CCodeDownload::OnProgress(ULONG Progress, ULONG ProgressMax, ULONG StatusCode, const char* StatusText)
- {
- #pragma unused (Progress, ProgressMax, StatusCode, StatusText)
- return S_OK;
- }
-
-
- //=--------------------------------------------------------------------------=
- // CCodeDownload::IBindStatusCallback::OnStopBinding
- //=--------------------------------------------------------------------------=
- //
- STDMETHODIMP
- CCodeDownload::OnStopBinding(HRESULT hresult, const char* Error)
- {
- #pragma unused (hresult, Error)
- // if (m_pib != NULL)
- // m_pib->Release();
- // m_pib = NULL;
-
- CodeAvailable(mDownloadResult);
- return S_OK;
- }
-
-
-
- //=--------------------------------------------------------------------------=
- // CCodeDownload::IBindStatusCallback::GetBindInfo
- //=--------------------------------------------------------------------------=
- //
- STDMETHODIMP
- CCodeDownload::GetBindInfo(DWORD* BINDF, BINDINFO *BindInfo)
- {
- *BINDF = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE;
- BindInfo->dwBindVerb = BINDVERB_GET;
- return S_OK;
- }
-
-
- //=--------------------------------------------------------------------------=
- // CCodeDownload::IBindStatusCallback::OnDataAvailable
- //=--------------------------------------------------------------------------=
- //
- STDMETHODIMP
- CCodeDownload::OnDataAvailable(DWORD BSCF, DWORD Size, FORMATETC* FormatEtc, STGMEDIUM* StgMedium)
- {
- #pragma unused (FormatEtc)
- if (StgMedium->tymed == TYMED_FILE)
- {
- Str255 fileName;
- FSSpec BinHexFile;
- FSSpec UnpackedFile;
-
- if (StgMedium->lpszFileName != NULL) {
- strncpy((char *) fileName, StgMedium->lpszFileName, 256);
- c2pstr((char *) fileName);
-
- if (FSMakeFSSpec(0, 0, fileName, &BinHexFile) == noErr)
- {
- if (IsBinHexFile(&BinHexFile, &UnpackedFile))
- {
- if (FindDownloadFolder(&UnpackedFile.vRefNum,
- &UnpackedFile.parID, false))
- {
- if (UnpackBinHexFile(&BinHexFile, &UnpackedFile, NULL))
- {
- RegisterOleFragment(&UnpackedFile, TRUE);
- mDownloadResult = TRUE;
- }
- }
- }
- }
- }
-
- CoTaskMemFree(StgMedium->lpszFileName);
- }
- else if ((StgMedium->tymed == TYMED_ISTREAM) && ((BSCF & BSCF_LASTDATANOTIFICATION) == 0))
- {
- if(!mStreamDataP)
- {
- mStreamDataP = (unsigned char *)CoTaskMemAlloc(Size);
- mStreamLength = 0;
- }
- else
- mStreamDataP = (unsigned char *) CoTaskMemRealloc(mStreamDataP, mStreamLength + Size);
-
- StgMedium->pstm->Read(mStreamDataP + mStreamLength, Size, NULL);
- mStreamLength += Size;
- mDownloadResult = TRUE;
- mEnd = (LPOLESTR) mStreamDataP + mStreamLength;
- }
- if (StgMedium->pUnkForRelease != NULL)
- StgMedium->pUnkForRelease->Release();
-
- return S_OK;
- }
-
-
- //=--------------------------------------------------------------------------=
- // CCodeDownload::IBindStatusCallback::OnObjectAvailable
- //=--------------------------------------------------------------------------=
- //
- STDMETHODIMP
- CCodeDownload::OnObjectAvailable(REFIID RefID, IUnknown* Unknown)
- {
- #pragma unused (RefID, Unknown)
- return S_OK;
- }
-
- //
- // RegisterOleFragment
- //
- // Calls the DllRegisterServer or DllUnregisterServer entrypoint of the
- // specified file.
- //
-
- HRESULT
- RegisterOleFragment(FSSpec *spec, BOOL fRegister)
- {
- HRESULT hr;
- CFragConnectionID connID;
- Ptr mainAddr;
- Str255 errName;
- StringPtr psymName;
- Ptr symAddr;
- CFragSymbolClass symClass;
-
- if (GetDiskFragment(spec, 0, kCFragGoesToEOF, nil, kLoadCFrag, &connID, &mainAddr,
- errName) == noErr) {
- psymName = fRegister ? "\pDllRegisterServer" : "\pDllUnregisterServer";
- if (FindSymbol(connID, psymName, &symAddr, &symClass) == noErr) {
- // DllRegisterServer/DllUnregisterServer have the same prototype.
- hr = ((LPFNREGISTERSERVER) symAddr)();
- } else {
- // We won't consider it an error if this fragment isn't self-
- // registering.
- hr = S_OK;
- }
- CloseConnection(&connID);
- } else {
- hr = ResultFromScode(CO_E_DLLNOTFOUND);
- }
-
- return hr;
- }
-
- #define IsSpace(ch) ((ch)==' ' || (ch)=='\t' || (ch)=='\n' || (ch)=='\r')
- #define IsEndOfLine(ch) ((ch)=='\n' || (ch)=='\r')
- #define ToUpper(ch) (((ch)>='A'&&(ch)<='Z') ? ((ch)-'A'+'a') : (ch))
- #define min(a,b) (((a) < (b)) ? (a) : (b))
-
- //
- // CInfStreamNotify::SkipWhitespace
- //
- // Moves the current pointer ahead to the first non-whitespace character.
- //
-
- void
- CCodeDownload::SkipWhitespace(void)
- {
- while (IsSpace(*mCurrent) && mCurrent < mEnd)
- mCurrent++;
- }
-
- //
- // CCodeDownload::SkipToNextLine
- //
- // Moves the current pointer ahead to the first non-whitespace character after
- // a end-of-line character.
- //
-
- void
- CCodeDownload::SkipToNextLine(void)
- {
- char ch;
- do {
- while (mCurrent < mEnd) {
- ch = *mCurrent++;
- if (IsEndOfLine(ch))
- break;
- }
- SkipWhitespace();
- } while (mCurrent < mEnd && *mCurrent == ';');
- }
-
- //
- // CCodeDownload::FindSection
- //
- // Moves the current pointer ahead to the first line after the section that
- // matches the specified section name. Returns TRUE if the section was found,
- // else FALSE.
- //
-
- BOOL
- CCodeDownload::FindSection(LPOLESTR pszSection)
- {
- BOOL fSecondPass;
- LPOLESTR pszStop;
- LPOLESTR pszSectionMatch;
- LPOLESTR pszSectionStart;
-
- fSecondPass = FALSE;
-
- // Start scanning from the start of the memory buffer or from the last
- // section where we found a match as an optimization.
- mCurrent = (mLastSectionMatch != NULL) ? mLastSectionMatch :
- (LPOLESTR) mStreamDataP;
- pszStop = mEnd;
-
- DoNextPass:
- SkipWhitespace();
- while (mCurrent < pszStop) {
- // As an optimization, if this is the section we're looking for,
- // we'll keep a pointer to it so that the next time FindSection is
- // called, we can start from there and catch multiple requests for
- // the same section.
- pszSectionStart = mCurrent;
- if (*mCurrent++ == '[') {
- pszSectionMatch = pszSection;
- while (mCurrent < pszStop && ToUpper(*mCurrent) ==
- ToUpper(*pszSectionMatch)) {
- mCurrent++;
- pszSectionMatch++;
- if (*pszSectionMatch == '\0') {
- if (mCurrent < pszStop && *mCurrent++ == ']') {
- mLastSectionMatch = pszSectionStart;
- SkipToNextLine();
- return TRUE;
- }
- break;
- }
- }
- }
- SkipToNextLine();
- }
-
- // If this is our first pass and we didn't begin from the base of the
- // memory buffer, then do another pass, this time from the base of the
- // buffer.
- if (!fSecondPass && mLastSectionMatch != NULL) {
- mCurrent = (LPOLESTR) mStreamDataP;
- pszStop = mLastSectionMatch;
- fSecondPass = TRUE;
- goto DoNextPass;
- }
-
- return FALSE;
- }
-
- //
- // CCodeDownload::GetProfileString
- //
- // Reads a string from the .inf file much like the Win32 GetProfileString API.
- // Returns TRUE if the specified section/key were found, else FALSE.
- //
-
- BOOL
- CCodeDownload::GetProfileString(LPOLESTR pszSection, LPOLESTR pszKey,
- LPOLESTR pszBuffer, UINT BufferSize)
- {
- LPOLESTR pszKeyMatch;
- LPOLESTR pszBufferBase;
-
- // FindSection will move the current pointer to the line immediately after
- // the section name, if the section exists.
- if (!FindSection(pszSection))
- return FALSE;
-
- while (mCurrent < mEnd && *mCurrent != '[') {
- pszKeyMatch = pszKey;
- while (mCurrent < mEnd && ToUpper(*mCurrent) ==
- ToUpper(*pszKeyMatch)) {
- mCurrent++;
- pszKeyMatch++;
- if (*pszKeyMatch == '\0') {
- SkipWhitespace();
- if (mCurrent < mEnd && *mCurrent == '=') {
- mCurrent++;
- SkipWhitespace();
- pszBufferBase = pszBuffer;
- while (mCurrent < mEnd &&
- !IsEndOfLine(*mCurrent) && *mCurrent != ';' &&
- BufferSize-- > 0) {
- *pszBuffer++ = *mCurrent++;
- }
- // Strip off any trailing whitespace from the buffer.
- while (pszBuffer > pszBufferBase && IsSpace(*(pszBuffer-1)))
- pszBuffer--;
- *pszBuffer = '\0';
- return TRUE;
- }
- break;
- }
- }
- SkipToNextLine();
- }
-
- return FALSE;
- }
-
- //
- // CCodeDownload::GetKeyCommon
- //
- // Common worker routine for GetFirstKeyName and GetNextKeyName. On entry, the
- // current pointer should be positioned at the first non-whitespace character
- // of the next candidate line.
- //
-
- BOOL
- CCodeDownload::GetKeyCommon(LPVOID *pvEnumKey, LPOLESTR pszBuffer, UINT
- BufferSize)
- {
- LPOLESTR pszKeyStart;
- UINT BytesToCopy;
-
- while (mCurrent < mEnd && *mCurrent != '[') {
- pszKeyStart = mCurrent;
- while (mCurrent < mEnd && !IsEndOfLine(*mCurrent)) {
- if (*mCurrent == '=') {
- while (mCurrent > pszKeyStart && IsSpace(*(mCurrent-1)))
- mCurrent--;
- BytesToCopy = min((UINT) (mCurrent - pszKeyStart),
- BufferSize - 1);
- memcpy(pszBuffer, pszKeyStart, BytesToCopy);
- pszBuffer[BytesToCopy] = '\0';
- *pvEnumKey = (LPVOID) pszKeyStart;
- return TRUE;
- }
- mCurrent++;
- }
- SkipToNextLine();
- }
-
- return FALSE;
- }
-
- //
- // CCodeDownload::GetFirstKey
- //
- // Returns the first key from the specified section. On return, pvEnumKey is a
- // "handle" that can be used in subsequents calls to GetNextKey.
- //
-
- BOOL
- CCodeDownload::GetFirstKey(LPOLESTR pszSection, LPVOID *pvEnumKey, LPOLESTR
- pszBuffer, UINT BufferSize)
- {
- // FindSection will move the current pointer to the line immediately after
- // the section name, if the section exists.
- if (!FindSection(pszSection))
- return FALSE;
-
- return GetKeyCommon(pvEnumKey, pszBuffer, BufferSize);
- }
-
- //
- // CCodeDownload::GetNextKey
- //
- // Returns the next key from the specified section using the "handle" returned
- // from previous GetFirstKey or GetNextKey calls.
- //
-
- BOOL
- CCodeDownload::GetNextKey(LPVOID *pvEnumKey, LPOLESTR pszBuffer, UINT
- BufferSize)
- {
- // On entry, pvEnumKey points at the line that contained the last
- // successful enumeration.
- mCurrent = (LPOLESTR) *pvEnumKey;
- SkipToNextLine();
-
- return GetKeyCommon(pvEnumKey, pszBuffer, BufferSize);
- }
-
- //
- // CheckCLSIDVersion
- //
- // Returns TRUE if the inproc server for the specified CLSID is at least the
- // specified minimum version, else returns FALSE.
- //
-
- BOOL
- CheckCLSIDVersion(REFCLSID /* rclsid */, DWORD /* dwMinimumVersion */)
- {
- BOOL fResult = FALSE;
- #if 0
- // BUGBUG
- FSSpec spec;
- DWORD dwFileVersion;
- if (SUCCEEDED(CoGetClassFSSpec(rclsid, CLSCTX_INPROC_SERVER, &spec))
- {
- if (dwMinimumVersion != 0)
- {
- if (GetVersionFromFile(&spec, &dwFileVersion) &&
- (dwMinimumVersion <= dwFileVersion))
- fResult = TRUE;
- }
- else
- {
- // No minimum version specified; simply checks that a handler for
- // the CLSID exists.
- fResult = TRUE;
- }
- }
- #endif
- return fResult;
- }
-